package Tests.ext
{
	import Box2D.Collision.Shapes.b2CircleShape;
	import Box2D.Collision.Shapes.b2EdgeShape;
	import Box2D.Collision.Shapes.b2PolygonShape;
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Common.Math.b2Vec2Array;
	import Box2D.Common.b2Color;
	import Box2D.Dynamics.Controllers.b2BuoyancyController;
	import Box2D.Dynamics.Controllers.b2BuoyancyControllerDef;
	import Box2D.Dynamics.Controllers.b2Controller;
	import Box2D.Dynamics.Joints.b2RevoluteJointDef;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2BodyDef;
	import Box2D.Dynamics.b2BodyType;
	import Box2D.Dynamics.b2Fixture;
	import Box2D.Dynamics.b2FixtureDef;
	
	import Framework.Test;
	
	public class Buoyancy extends Test
	{
		private var m_controller:b2BuoyancyController
		private var m_uppers:Array = [];
		private var floated:Boolean = true
		public function Buoyancy()
		{
			super();
			createGround()
			createController();
			createBodiesUpper();
			createBodiesLower();
			createBridge();
		}
		public override function get hotKeyNote():String
		{
			return '(d) change density of uppers';
		}
		private function createGround():void{
			var shape:b2EdgeShape = new b2EdgeShape;
			shape.Set(new b2Vec2(-40,0),new b2Vec2(40,0));
			m_groundBody.CreateFixtureByShape(shape,0);
		}
		private function createController():void{
			var bcd:b2BuoyancyControllerDef = new b2BuoyancyControllerDef;
			bcd.offset = 15;
			bcd.normal = new b2Vec2(0,1);
			bcd.density = 2;
			bcd.linearDrag = 2;
			bcd.angularDrag = 1;
			m_controller = m_world.CreateController(bcd) as b2BuoyancyController;
		}
		private function createBodiesUpper():void{
			var shape:b2PolygonShape = new b2PolygonShape;
			var vertices:b2Vec2Array = new b2Vec2Array(3);
			vertices.setAt2(0,-.5,0);
			vertices.setAt2(1,.5,0);
			vertices.setAt2(2,0,1.5);
			shape.Set(vertices,3);
			var fd:b2FixtureDef = new b2FixtureDef;
			fd.density = 1;
			fd.shape = shape;
			for(var i:int=0;i<2;i++){
				var bd:b2BodyDef = new b2BodyDef;
				bd.position.Set(-8+8*i,12);
				bd.type = b2BodyType.b2_dynamicBody;
				var body:b2Body = m_world.CreateBody(bd);
				body.CreateFixture(fd);
				m_controller.AddBody(body);
				m_uppers.push(body);
			}
		}
		private function createBodiesLower():void{
			var shape:b2CircleShape = new b2CircleShape
			shape.radius = .5;			
			var fd:b2FixtureDef = new b2FixtureDef;
			fd.density = 2;
			fd.shape = shape;
			for(var i:int=0;i<3;i++){
				var bd:b2BodyDef = new b2BodyDef;
				bd.position.Set(-6+6*i,10);
				bd.type = b2BodyType.b2_dynamicBody;
				var body:b2Body = m_world.CreateBody(bd);
				body.CreateFixture(fd);
				m_controller.AddBody(body);
			}
		}
		private function createBridge():void{
			var shape:b2PolygonShape = new b2PolygonShape;
			shape.SetAsBox(.5,.125);
			var fd:b2FixtureDef = new b2FixtureDef;
			fd.density = 20;
			fd.friction = .2;
			fd.shape = shape;
			
			var jd:b2RevoluteJointDef = new b2RevoluteJointDef;
			var numPlanks:int = 30;
			
			var prevBody:b2Body = m_groundBody;			
			for(var i:int=0;i<numPlanks;++i){
				var bd:b2BodyDef = new b2BodyDef;
				bd.type = b2BodyType.b2_dynamicBody;
				bd.position = new b2Vec2(-14.5+1*i,5);
				var body:b2Body = m_world.CreateBody(bd);
				body.CreateFixture(fd);
				
				var anchor:b2Vec2 = new b2Vec2(-15+1*i,5);
				jd.Initialize(prevBody,body,anchor);
				m_world.CreateJoint(jd);
				
				prevBody = body;
				m_controller.AddBody(body);
			}
			jd.Initialize(prevBody,m_groundBody,new b2Vec2(-15+1*numPlanks,5));
			m_world.CreateJoint(jd);
		}
		public override function Step():void
		{
			super.Step();
			writeMessage(floated?'floated':'');
			//draw the water
			var vertices:Array = [
				new b2Vec2(-40,m_controller.offset)
				,new b2Vec2(40,m_controller.offset)
				,new b2Vec2(40,0)
				,new b2Vec2(-40,0)
			];
			var color:b2Color = new b2Color;
			color.Set(.7,.1,1);
			m_debugDraw.DrawPolygonAlpha(vertices,4,color,0,.2);
		}
		public override function Key(code:String):void
		{
			switch(code){
				case 'd':
					for each(var body:b2Body in m_uppers)
					{
						body.GetFixtureList().SetDensity(floated?3:1);
						body.ResetMassData();
					}
					floated = !floated;
					break;
			}
		}
	}
}